package com.atguigu.tingshu.album.service.impl;

import cn.hutool.core.lang.Assert;
import com.alibaba.cloud.sentinel.feign.SentinelContractHolder;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.model.user.UserPaidTrack;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserFeignClient;

import com.atguigu.tingshu.vo.album.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.awt.desktop.AboutHandler;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

	@Autowired
	private TrackInfoMapper trackInfoMapper;

	@Autowired
	private VodService vodService;

	@Autowired
	private AlbumInfoMapper albumInfoMapper;

	@Autowired
	private TrackStatMapper trackStatMapper;

	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private AlbumStatMapper albumStatMapper;

	@Autowired
	private UserFeignClient userFeignClient;



	/**
	 * 保存声音
	 * @param trackInfo
	 */
	@Override
	public void saveTackInfo(TrackInfo trackInfo) {
		//声音信息表
		Long userId = AuthContextHolder.getUserId();
		trackInfo.setUserId(userId);
		trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);
		//声音来源
		trackInfo.setSource("1");
		//排序 查询专辑加1
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
		trackInfo.setOrderNum(albumInfo.getIncludeTrackCount() +1);

		//声音的时长大小 等参数 在腾讯云里面
		TrackMediaInfoVo trackMediaInfoVo= vodService.getTrackMediaInfo(trackInfo.getMediaFileId());
		if(trackMediaInfoVo!=null){
			trackInfo.setMediaDuration(new BigDecimal(trackMediaInfoVo.getDuration()));
			// trackInfo.setMediaUrl(trackMediaInfoVo.getMediakUrl());
			trackInfo.setMediaSize(trackMediaInfoVo.getSize());
			trackInfo.setMediaType(trackMediaInfoVo.getType());

		}
		trackInfoMapper.insert(trackInfo);

		//声音统计
		this.saveTackStat(trackInfo.getId(),SystemConstant.TRACK_STAT_PLAY,0);
		this.saveTackStat(trackInfo.getId(),SystemConstant.TRACK_STAT_COLLECT,0);
		this.saveTackStat(trackInfo.getId(),SystemConstant.TRACK_STAT_PRAISE,0);
		this.saveTackStat(trackInfo.getId(),SystemConstant.TRACK_STAT_COMMENT,0);

		//专辑表统计的维护
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() +1);
		albumInfoMapper.updateById(albumInfo);

	}


	/**
	 * 获取当前用户声音分页列表
	 * @param page1 分页信息
	 * @param trackInfoQuery  条件
	 * @return
	 */
	@Override
	public Page<TrackListVo> findUserTrackPage(Page page1, TrackInfoQuery trackInfoQuery) {
		Long userId = AuthContextHolder.getUserId();
		trackInfoQuery.setUserId(userId);
		return trackInfoMapper.selectUserTrackPage(page1,trackInfoQuery);
	}


	/**
	 * 修改声音信息
	 * @param id 声音id
	 * @param trackInfo 修改内容
	 */
	@Override
	public void updateTrackInfo(Long id, TrackInfo trackInfo) {
		//主要判断声音视频是否更改
		String mediaFileIdBefore = trackInfo.getMediaFileId();
		TrackInfo trackInfo1 = trackInfoMapper.selectById(id);
		//数据库的声音标识
		String mediaFileIdAfter = trackInfo1.getMediaFileId();


		if(mediaFileIdAfter !=mediaFileIdBefore){
			//声音修改了 重新查询云点播信息
			TrackMediaInfoVo trackMediaInfo = vodService.getTrackMediaInfo(mediaFileIdAfter);
			trackInfo.setMediaDuration(new BigDecimal(trackMediaInfo.getDuration()));
			trackInfo.setMediaSize(trackMediaInfo.getSize());
			trackInfo.setMediaType(trackMediaInfo.getType());
			//删除云点播视频
			vodService.deleteTrackMedia(mediaFileIdBefore);
		}

		trackInfo.setId(id);
		//更新
		trackInfoMapper.updateById(trackInfo);
	}


	/**
	 * 删除声音信息
	 * @param id 信息id
	 */
	@Override
	public void removeTrackInfo(Long id) {
		TrackInfo trackInfo = trackInfoMapper.selectById(id);
		Long albumId = trackInfo.getAlbumId();
		Integer orderNum = trackInfo.getOrderNum();


		//先删除声音基本信息
		trackInfoMapper.deleteById(id);

		//删除声音统计
		trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId,id));

		//删除云点播信息
		vodService.deleteTrackMedia(trackInfo.getMediaFileId());

		//删除声音信息后维护声音表的 order_num列 排序
		/**
		 * update track_info ti set order_num =order_num -1 where order_num >? and album_id =1
		 */
		trackInfoMapper.updateOrderNum(albumId,orderNum);

		//专辑表的总数减1
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		Integer includeTrackCount = albumInfo.getIncludeTrackCount();
		albumInfo.setIncludeTrackCount(includeTrackCount -1);
		albumInfoMapper.updateById(albumInfo);



	}

	/**
	 * 增加播放量
	 * @param trackStatMqVo
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateTrackStat(TrackStatMqVo mqVo) {

		String key = "mq:" + mqVo.getBusinessNo();
		//1、TODO  做消息幂等性 redis消息分布式锁
		try {
			Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, mqVo.getBusinessNo(), 1, TimeUnit.HOURS);
			if(flag){
				//执行操作
				//更新声音 传来的声音的类型

				trackStatMapper.updateStart(mqVo.getTrackId(),mqVo.getStatType(),mqVo.getCount());

				//更新专辑
				if(mqVo.getStatType().equals(SystemConstant.TRACK_STAT_PLAY)){
					//播放量
					albumStatMapper.updateStart(mqVo.getAlbumId(),SystemConstant.ALBUM_STAT_PLAY,mqVo.getCount());
				}
				if(mqVo.getStatType().equals(SystemConstant.TRACK_STAT_COMMENT)){
					//评论量
					albumStatMapper.updateStart(mqVo.getAlbumId(),SystemConstant.ALBUM_STAT_COMMENT,mqVo.getCount());
				}

			}
		} catch (Exception e) {
			redisTemplate.delete(key);
			throw  new RuntimeException(e);

		}


	}



	/**
	 * 根据声音ID，查询声音统计信息
	 * @param trackId
	 * @return
	 */
	@Override
	public TrackStatVo getTrackStatVo(Long trackId) {
		return trackInfoMapper.getTrackStatVo(trackId);
	}


	/**
	 * 获取用户声音分集购买支付列表5
	 * @param trackId
	 * @return
	 */
	@Override
	public List<Map<String, Object>> findUserTrackPaidList(Long trackId) {
		List<Map<String, Object>> mapList = new ArrayList<>();
		//这个是前端传过来的用户的声音id
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
		//1.获取用户已经购买过的声音
		List<Long> longList = userFeignClient.findUserPaidTrackList(trackInfo.getAlbumId()).getData();
		Assert.notNull(longList,"获取用户已经购买过的声音失败");

		//2.再获取用户正常需要购买的声音
		List<TrackInfo> trackInfoList =  trackInfoMapper.selectXuYaoBuy(trackInfo.getAlbumId(),trackInfo.getOrderNum());
		//3.刷选出用户还需要购买的声音
		List<TrackInfo> collect1 = trackInfoList.stream().filter(trackInfo1 -> {
			return !longList.contains(trackInfo1.getId());
		}).collect(Collectors.toList());

		//4.根据专辑的数量变量遍历获取分集
		//获取价格信息
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
		Map<String, Object> map = new HashMap<>();
		BigDecimal price = albumInfo.getPrice();
		map.put("price",price);
		map.put("name","本集");
		map.put("trackCount",1);
		mapList.add(map);


		/**
		 *  TODO 分级购买专辑i<=40是前端只能展示 本集 10 20 30 40 n
		 * i<=30 count不能等于 如果等于 30 会出现两遍30
		 * i<=30 要等于 不等于会少一次
		 * i<=40 不等于就会少一次循环 30不会出现
		 */
		//count =30
		int count = collect1.size();
		for (int i = 10; i <= 40; i += 10) {
			//判断数量>i 固定显示后i集
			if (i <= 30 && count >i) {
				Map<String, Object> map1 = new HashMap<>();
				map1.put("name", "后" + i + "集");
				map1.put("price", price.multiply(new BigDecimal(i)));
				map1.put("trackCount", i);
				mapList.add(map1);
			} else {
				//反之全集（动态构建后count集合）
				Map<String, Object> map1 = new HashMap<>();
				map1.put("name", "后" + count + "集");
				map1.put("price", price.multiply(new BigDecimal(count)));
				map1.put("trackCount", count);
				mapList.add(map1);
				break;
			}
		}
		return mapList;
	}



	private void saveTackStat(Long id, String trackStatPlay, int i) {
		TrackStat trackStat = new TrackStat();
		trackStat.setTrackId(id);
		trackStat.setStatType(trackStatPlay);
		trackStat.setStatNum(i);
		trackStatMapper.insert(trackStat);
	}
}
